package ar.edu.caece.pl.asin.model.impl;

import ar.edu.caece.pl.alex.model.IToken;
import ar.edu.caece.pl.alex.model.impl.Token;
import ar.edu.caece.pl.asin.manager.IAnalizadorSintactico;
import ar.edu.caece.pl.asin.manager.impl.AbstractAnalizadorSintactico;
import ar.edu.caece.pl.asin.model.ITokenStream;

public class Var1 extends AbstractAnalizadorSintactico implements IAnalizadorSintactico {
	
	/* INICIALIZACION */	
	public Var1 ( ITokenStream ts ) {
		super(ts, false);
	}
	public Var1 ( ITokenStream ts, boolean debugMode ) {
		super(ts,debugMode);
	}

	
	/**
	 * Devuelve true si reconoce un tipo, un arreglo o multiples definiciones de variable
	 */
	public boolean reconocer () {
		
		boolean recognized = true; //(asumimos correctitud hasta demostrar lo contrario)
		
		//----------------------------------------------
		//Agrego info de debug de la produccion
		em.debug( "Reconocer Var1", this.getTokenSiguiente() );
		//----------------------------------------------
	
		/* <VAR_1> -> , <VAR>    |
                      : <TIPO>;   |
                      [ <VAR_2>	 */
		
		if ( this.getTokenSiguiente().getType() == IToken.TYPE_COMA ){
			
			// <VAR_1> -> , <VAR>
			
			//----------------------------------------------
			//Agrego info de debug de la produccion
			em.debug( "<VAR_1> -> , <VAR>", this.getTokenSiguiente() );
			//----------------------------------------------
			
			//Reconocer Coma
			if ( !this.reconocerToken(IToken.TYPE_COMA) ) {
				//El reconocerToken() habria adelantado el tokenStream hasta salir de esta iteracion de Var1,
				//entonces no hay que seguir buscando sino salir
				return false;
			}
			
			// Espio el siguiente para ver si es correcto.
			if ( ! Var.primeros( this.getTokenSiguiente() ) ) {
				
				em.error("Se esperaba nueva variable", this.getTokenSiguiente());
				recognized = false;
				
				//Tratamiento de errores
				em.recover(this.getClass(), this.tokenStream);
			}
			// Vuelvo a iterar el while de <VAR>.
			
		} else if ( this.getTokenSiguiente().getType() == IToken.TYPE_DOS_PUNTOS ) {
			
			// <VAR_1> -> : <TIPO>;
			
			//----------------------------------------------
			//Agrego info de debug de la produccion
			em.debug( "<VAR_1> -> : <TIPO> ;", this.getTokenSiguiente() );
			//----------------------------------------------
			
			//Reconocer dos puntos
			if ( !this.reconocerToken(IToken.TYPE_DOS_PUNTOS) ) {
				return false;
			}
			
			//Reconocer Tipo
			IAnalizadorSintactico tipo = new Tipo(this.tokenStream, this.debugMode);
			recognized &= tipo.reconocer();
			
			//Reconocer punto y coma
			if ( !this.reconocerToken(IToken.TYPE_PUNTO_COMA) ) {
				return false;
			}
			
			//LISTO la definicion de variable
			
		} else if ( this.getTokenSiguiente().getType() == IToken.TYPE_CORCHETE_IZQ ){

			// <VAR_1> -> [ <VAR_2>
			
			//----------------------------------------------
			//Agrego info de debug de la produccion
			em.debug( "<VAR_1> -> [ <VAR_2>", this.getTokenSiguiente() );
			//----------------------------------------------
			
			//Reconocer Corchete [ izq
			if ( !this.reconocerToken(IToken.TYPE_CORCHETE_IZQ) ) {
				return false;
			}
			
			IAnalizadorSintactico var2 = new Var2(this.tokenStream, this.debugMode);
			recognized &= var2.reconocer();

		} else {
			
			//No deberia darse el caso, pero si se llama a reconocer() en un estado incorrecto deberia salir por aqui
			em.error("Se esperaba token "+ this.dic.getTokenDescription(IToken.TYPE_COMA) +
					 " o " + this.dic.getTokenDescription(IToken.TYPE_DOS_PUNTOS) +
					 " o " + this.dic.getTokenDescription(IToken.TYPE_CORCHETE_IZQ), this.getTokenSiguiente());
			recognized = false;
			
			//Tratamiento de errores
			em.recover(this.getClass(), this.tokenStream);
		}

		return recognized;
	}
	
	public static boolean primeros(IToken token) {
		return  token.equals( new Token(IToken.TYPE_COMA) )||
				token.equals( new Token(IToken.TYPE_DOS_PUNTOS) ) ||
				token.equals( new Token(IToken.TYPE_CORCHETE_IZQ) );
	}
}
